/*
@file: SignalManager.cpp
@author: ZZH
@date: 2022-10-18
@info: 信号管理器, 用于导入导出信号列表
*/
#include "SignalListWidget.h"
#include "SignalItem.h"
#include "symTable.h"
#include "log.h"
#include <QMouseEvent>
#include <QTouchEvent>

SignalListWidget::SignalListWidget(QWidget* parent): QListWidget(parent), startPoint(0, 0)
{
    this->setAttribute(Qt::WA_AcceptTouchEvents);
    this->pTouchTimer = new QTimer(this);
    this->pTouchTimer->setSingleShot(true);
    this->pTouchTimer->stop();

    connect(this->pTouchTimer, &QTimer::timeout, this, [this]() {emit customContextMenuRequested(this->startPoint.toPoint());});
}

void SignalListWidget::load(const QJsonArray& arr)
{
    for (const auto& item : arr)
    {
        QJsonObject sigObj = item.toObject();
        const QString& sigName = sigObj[this->nameKey].toString();
        const QString& sigCode = sigObj[this->codeKey].toString();
        bool isFFTMode = sigObj[this->isFFTKey].toBool();

        if (not SigSymTable.has(sigName))
        {
            auto newItem = new SignalItem(sigName);

            newItem->setSourceCode(sigCode);
            newItem->setFFTMode(isFFTMode);
            this->addItem(newItem);
            SigSymTable.insert(sigName, newItem);//这里的insert必然成功, 因为上面已经检查了是否重名
            UI_INFO("Add signal: %s", sigName.toStdString().c_str());
        }
        else//导入的信号和已有信号冲突, 选择放弃导入的信号, 保留工作区现有信号
        {
            UI_INFO("Skip %s because name conflict", sigName.toStdString().c_str());
        }
    }
}

QJsonArray SignalListWidget::save(void)
{
    QJsonArray arr;
    const int itemCount = this->count();

    for (int i = 0;i < itemCount;i++)
    {
        QJsonObject oneSig;
        auto item = static_cast<SignalItem*>(this->item(i));
        oneSig[this->nameKey] = item->text();
        oneSig[this->codeKey] = item->getSourceCode();
        oneSig[this->isFFTKey] = item->getFFTMode();
        arr.append(oneSig);
    }

    return arr;
}

bool SignalListWidget::event(QEvent* event)
{
    QTouchEvent* te = static_cast<QTouchEvent*>(event);
    switch (event->type())
    {
        case QEvent::TouchBegin:
        {
            this->startPoint = te->touchPoints().first().pos();
            QMouseEvent* e = new QMouseEvent(QEvent::MouseButtonPress, this->startPoint,
            Qt::MouseButton::LeftButton, Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier);
            QListWidget::mousePressEvent(e);

            this->pTouchTimer->start(400);
            te->accept();
            return true;
        }

        case QEvent::TouchUpdate:
        {
            const QPointF &thisPoint = te->touchPoints().first().pos();
            auto diff = thisPoint - this->startPoint;

            qreal distance = sqrt(diff.x() * diff.x() + diff.y() * diff.y());
            if (distance > 20)
                this->pTouchTimer->stop();

            return QListWidget::event(event);
        }

        case QEvent::TouchCancel:
        case QEvent::TouchEnd:
            this->pTouchTimer->stop();
            return QListWidget::event(event);

        default:
            return QListWidget::event(event);
            break;
    }
}
